package com.gomoku

import android.os.Bundle
import android.os.Handler.Callback
import android.os.Message
import android.view.Menu
import android.view.MenuItem
import android.view.MenuItem.OnMenuItemClickListener
import android.widget.Toast

import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color

import com.common.InputBox
import com.common.MessageBox
import com.gomoku.ui.theme.GomokuClientTheme

import kotlin.system.exitProcess

// 主活动
class MainActivity: ComponentActivity(), Callback, OnMenuItemClickListener {
    private var mGame: Game? = null                         // 游戏
    private lateinit var mInputBox: InputBox                // 输入窗口
    private lateinit var mMenuItemDefeat: MenuItem          // "认输"菜单项
    private lateinit var mMenuItemFindUsers: MenuItem       // "寻找其它用户"菜单项
    private lateinit var mMenuItemRestart: MenuItem         // "再来一局"菜单项
    private lateinit var mMessageBox: MessageBox            // 消息窗口
    private lateinit var mRivalName: MutableState<String>   // 当前对手名字
    private lateinit var mRivalWindow: RivalWindow          // 对手列表窗口

    /**
     * 界面布局。
     */
    @Composable
    fun Greeting() {
        // 计算格的尺寸
        val gridCount = Const.GAME_BOARD_POINT_COUNT_H + 1
        Const.GRID_SIZE = (resources.displayMetrics.widthPixels / gridCount).toFloat()

        // 计算游戏区域的尺寸
        val gameBoardSize = Const.GRID_SIZE * gridCount

        // 创建游戏
        if (mGame == null) {
            mGame = Game(this)
        }

        // 布局
        Column(Modifier
            .fillMaxSize()
            .background(Color.Black), Arrangement.Center, Alignment.Start) {
            // 初始化成员
            mInputBox.Greeting("")
            mMessageBox.Greeting()
            mRivalName = remember {
                mutableStateOf(super.getString(R.string.IDS_CURRENT_RIVAL))
            }
            mRivalWindow.Greeting()

            // 游戏区域
            mGame!!.GameBoard(gameBoardSize)

            // "当前对手"标签
            Text(
                text = mRivalName.value,
                color = Color.White
            )
        }
    }

    /**
     * 自定义事件的响应方法。
     * @param message   事件相关信息
     * @return 事件在此被处理则返回 true，否则返回 false
     */
    override fun handleMessage(message: Message): Boolean {
        when (message.what) {
            Const.UM_CONNECTED -> {
                this.onConnected(message.obj as Boolean)
                return true
            }
            Const.UM_GET_FIND_USERS_RESULT -> {
                this.onGetFindUsersResult(message.obj as FindUsersResult)
                return true
            }
            Const.UM_GAME_OVER -> {
                this.onGameOver(GameOverReason.entries[message.arg1])
                return true
            }
            Const.UM_GAME_START -> {
                this.onGameStart(message.obj as String)
                return true
            }
            Const.UM_GET_INVITE_REQUEST -> {
                this.onGetInviteRequest(message.obj as String)
                return true
            }
            Const.UM_GET_INVITE_RESULT -> {
                this.onGetInviteResult(message.obj as String, message.arg1 == 1)
                return true
            }
            Const.UM_GET_LOGON_RESULT -> {
                this.onGetLogonResult(message.obj as Boolean)
                return true
            }
            Const.UM_GET_RIVAL_NAME -> {
                this.onGetRivalName(message.obj as String)
                return true
            }
            Const.UM_RIVAL_QUIT_GAME -> {
                this.onRivalQuitGame(message.arg1 == 1, message.obj as String)
                return true
            }
        }
        return false
    }

    /**
     * 网络连接完成事件的响应方法。
     * @param result    成功则为 true，否则为 false
     */
    private fun onConnected(result: Boolean) {
        if (result) {
            // 登录
            mInputBox.show(
                tipText = super.getString(R.string.IDS_INPUT_USERNAME),
                onCancel = {
                    mGame!!.close()
                    exitProcess(0)
                },
                onOKString = {
                    mGame!!.logon(it)
                }
            )
        } else {
            // 弹出提示
            mMessageBox.show(
                okButtonText = super.getString(android.R.string.ok),
                onOK = {
                    exitProcess(0)
                },
                tipText = super.getString(R.string.IDS_NETWORK_ERROR)
            )
        }
    }

    /**
     * 创建事件的响应方法。
     * @param savedInstanceState   保存的实例状态
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.enableEdgeToEdge()

        // 初始化成员
        mInputBox = InputBox()
        mMessageBox = MessageBox()
        mRivalWindow = RivalWindow()

        // 设置内容
        this.setContent {
            GomokuClientTheme {
                this.Greeting()
            }
        }
    }

    /**
     * 创建菜单事件的响应方法。
     * @param menu  菜单
     * @return 总是 true
     */
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        super.getMenuInflater().inflate(R.menu.main, menu)

        // 创建菜单项
        mMenuItemDefeat = menu.findItem(R.id.IDC_DEFEAT)
        mMenuItemFindUsers = menu.findItem(R.id.IDC_FIND_RIVAL)
        mMenuItemRestart = menu.findItem(R.id.IDC_RESTART)

        // 菜单项添加事件监听者
        mMenuItemDefeat.setOnMenuItemClickListener(this)
        mMenuItemFindUsers.setOnMenuItemClickListener(this)
        mMenuItemRestart.setOnMenuItemClickListener(this)

        return true
    }

    /**
     * 销毁事件的响应方法。
     */
    public override fun onDestroy() {
        super.onDestroy()
        mGame!!.close()
    }

    /**
     * 游戏结束事件的响应方法。
     * @param reason    结束原因
     */
    private fun onGameOver(reason: GameOverReason) {
        // 设置菜单项
        mMenuItemFindUsers.isEnabled = true
        mMenuItemDefeat.isEnabled = false
        mMenuItemRestart.isEnabled = true

        // 显示提示信息
        val stringId = when (reason) {
            GameOverReason.LOST -> R.string.IDS_LOST
            GameOverReason.RIVAL_ADMIT -> R.string.IDS_RIVAL_ADMIT
            GameOverReason.SELF_ADMIT -> R.string.IDS_SELF_ADMIT
            GameOverReason.WON -> R.string.IDS_WON
            else -> { 0 }
        }
        mMessageBox.show(
            okButtonText = super.getString(android.R.string.ok),
            tipText = super.getString(stringId)
        )
    }

    /**
     * 游戏开始事件的响应方法。
     * @param rivalName 对手的名字
     */
    private fun onGameStart(rivalName: String) {
        // 隐藏对手列表窗口
        mRivalWindow.hide()

        // 设置菜单项
        mMenuItemFindUsers.isEnabled = false
        mMenuItemDefeat.isEnabled = true
        mMenuItemRestart.isEnabled = false

        // 显示对手的名字
        mRivalName.value = super.getString(R.string.IDS_CURRENT_RIVAL) + rivalName
    }

    /**
     * 得到寻找用户结果事件的响应方法。
     * @param result    结果
     */
    private fun onGetFindUsersResult(result: FindUsersResult) {
        if (!result.mUsernameList.isEmpty()) {
            mRivalWindow.setUsernameList(result.mUsernameList)
            mRivalWindow.show(onOK = {
                mGame!!.invite(it)
            })
        }
    }

    /**
     * 得到挑战请求事件的响应方法。
     * @param rivalName 对手的名字
     */
    private fun onGetInviteRequest(rivalName: String) {
        val question = rivalName + super.getString(R.string.IDS_INVITE)
        mMessageBox.show(
            tipText = question,
            cancelButtonText = super.getString(android.R.string.no),
            onCancel = {
                mGame!!.acceptInvite(rivalName, false)
            },
            okButtonText = super.getString(android.R.string.yes),
            onOK = {
                mGame!!.acceptInvite(rivalName, true)
            }
        )
    }

    /**
     * 得到挑战结果事件的响应方法。
     * @param rivalName 对手的名字
     * @param accept    接受挑战则为 true，否则为 false
     */
    private fun onGetInviteResult(rivalName: String?, accept: Boolean) {
        var information = rivalName
        information += if (accept) {
            super.getString(R.string.IDS_ACCEPT)
        } else {
            super.getString(R.string.IDS_REFUSE)
        }
        mMessageBox.show(
            okButtonText = super.getString(android.R.string.ok),
            tipText = information
        )
    }

    /**
     * 得到登录结果事件的响应方法。
     * @param succeeded 登录结果
     */
    private fun onGetLogonResult(succeeded: Boolean) {
        if (succeeded) {
            Toast.makeText(this, R.string.IDS_LOGON_SUCCEEDED, Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, R.string.IDS_LOGON_FAILED, Toast.LENGTH_SHORT).show()
            mInputBox.show(tipText = super.getString(R.string.IDS_INPUT_USERNAME))
        }
    }

    /**
     * 获取对手的名字事件的响应方法。
     * @param rivalName 对手的名字
     */
    private fun onGetRivalName(rivalName: String) {
        mGame!!.invite(rivalName)
    }

    /**
     * 所有菜单项的单击响应方法。
     * @param item  用户单击的菜单项
     * @return 事件在此被处理则返回 true，否则返回 false
     */
    override fun onMenuItemClick(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.IDC_DEFEAT -> {
                this.onMenuItemDefeatClicked()
                return true
            }
            R.id.IDC_FIND_RIVAL -> {
                this.onMenuItemFindUsersClicked()
                return true
            }
            R.id.IDC_RESTART -> {
                this.onMenuItemRestartClicked()
                return true
            }
        }

        return false
    }

    /**
     * "认输"菜单项的单击响应方法。
     */
    private fun onMenuItemDefeatClicked() {
        mGame!!.defeat()
    }

    /**
     * "寻找其它用户"菜单项的单击响应方法。
     */
    private fun onMenuItemFindUsersClicked() {
        mGame!!.findUsers()
    }

    /**
     * "再来一局"菜单项的单击响应方法。
     */
    private fun onMenuItemRestartClicked() {
        mGame!!.restart()
    }

    /**
     * 对手退出游戏事件的响应方法。
     * @param escape    对手逃跑则为 true，正常退出则为 false
     * @param rivalName 对手的名字
     */
    private fun onRivalQuitGame(escape: Boolean, rivalName: String) {
        // 设置菜单项
        mMenuItemFindUsers.isEnabled = true
        mMenuItemDefeat.isEnabled = false
        mMenuItemRestart.isEnabled = false

        // 设置状态栏
        mRivalName.value = super.getString(R.string.IDS_CURRENT_RIVAL)

        // 显示提示信息
        var text = rivalName
        if (escape) {
            text += super.getString(R.string.IDS_RIVAL_ESCAPE)
            mMessageBox.show(tipText = text)
        } else {
            text += super.getString(R.string.IDS_RIVAL_QUIT)
            Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
        }
    }
}
